package DataTags;
import java.io.File;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Hiber.Manager;;

/**
 * this class will implements the treatment with the tags
 * and the file's description as they are stored in DB
 * @author oz
 */
public class DataTagsAdapterDB implements DataTagsAdapter{
	/**
	 * when i want to enter a file name and to get its tags list
	 */
	private SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
	private DataTagsToFiles myTags;
	public DataTagsAdapterDB(DataTagsToFiles yourTags){
		myTags=yourTags;
	}
	/**
	 * when we enter file it will search for its tags
	 * if we enter tag it will search for its files
	 * @param String searchItem
	 * @param boolean flag
	 */
	public String searchFor(String searchItem,boolean flag){
		String tags="";
		if(flag){
			/**
			 * if we inserted a filename and want to find its tags
			 */
			List<DataTagsToFiles> l=tagsOfFile(searchItem);
			Iterator<DataTagsToFiles>it=l.iterator();
			tags="";
			while(it.hasNext())
			{
			
				tags=tags+it.next().getTag()+"@";
		
			}
		}
		else
		{
			/**
			 * if we insert a tag and want to find its files
			 */
			List<files> l=filesOfTag(searchItem);
			Iterator<files>it=l.iterator();
			tags="";
			while(it.hasNext())
			{
				files thisfile=it.next();
				tags=tags+thisfile.getName()+"	"+thisfile.getID()+"	"+thisfile.getPath()+"	"+thisfile.getLast_m()+"@";
			
			}
		}
		return tags;
	}
	/**
	 * @param String tag
	 * @return list of files with this tag
	 */
	public List<files> filesOfTag(String tag){
		
		String q;
		//String operator;
		q=
			"select f "+
			"from  files f "+
			"where f.ID in ( "+
								"select t.fileID "+
								"from DataTagsToFiles t "+
								"where (t.tag like :rep1)"+
						")"+
			" group by f.name";
		return  SearchFiles(q,tag);
	}
	/**
	 * @param String filename
	 *  @return list of tags with this filename
	 */
	public List<DataTagsToFiles> tagsOfFile(String filename){
		String q=
		"select t "+
			"from  DataTagsToFiles t "+
			"where t.fileID  in ( "+
								"select f.ID "+
								"from files f "+
								"where (f.name like :rep1)"+
							") "+
			"group by t.tag";
		return searchTags(q,filename);
	}
	/**
	 * searches for the tags
	 * @param q = query,
	 * @param String searchItem
	 * @return list of tags
	 */
	public List<DataTagsToFiles> searchTags(String query,String searchItem){
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		//Query q = session.createQuery("select t from files  join DataTagsToFiles  where name=:filename");
		String qStatment=query;
		
		Query q=session.createQuery(qStatment).setParameter("rep1",searchItem);
		//Query q=session.createQuery(qStatment);

		List<DataTagsToFiles> myTags=q.list();
		session.flush();
		session.close();
		return myTags;
	}
	/**
	 * the simple search
	 *  @return list of all tags in the DB
	 */
	public List<DataTagsToFiles> simpleSearchAllTags(){
		String qSt=
			"select d "+
			"from  DataTagsToFiles d "+
			"group by d.tag";
		
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		Query q=session.createQuery(qSt);
		List<DataTagsToFiles> myTags=q.list();
		session.flush();
		session.close();
		return myTags;
	}
	/**
	 * the simple search
	 * @return list of all files in the DB
	 */
	public List<files> simpleSearchAllFiles(){
		String qSt=
			"select f "+
			"from  files f "+
			"group by f.name";
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		Query q=session.createQuery(qSt);
		List<files> myfiles=q.list();
		session.flush();
		session.close();
		return myfiles;
	}
	/**
	 * searches for files
	 * @param String q=query , String searchItem 
	 * @return list of files
	 */
	public List<files> SearchFiles(String query,String searchItem){
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		//Query q = session.createQuery("select t from files  join DataTagsToFiles  where name=:filename");
		String qStatment=query;
		
		Query q=session.createQuery(qStatment).setParameter("rep1",searchItem);
		//Query q=session.createQuery(qStatment);
		List<files> myfiles=q.list();
		session.flush();
		session.close();
		return myfiles;
	}
	/**
	 * when I want to added a new file with its 
	 * tag list
	 * @param filename - String
	 * @param last_m -String
	 * @param path - String
	 * @param tags -String[]
	 */
	public void addTagsTo(String filename,String last_m,String path,String []tags){
		/*
		 * openning a new session 
		 * with the DB
		 */
		int []fileIDarr=new int [1000];
		int n;//number of files we need to add to them tags
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		Query q=session.createQuery("select f from files f where f.name=:rep1 and f.path=:rep2").setParameter("rep1", filename).setParameter("rep2",path);
		List <files>myfile=q.list();
		int fileID=0;
		if(q.list().isEmpty()){/*there is no such a file in our DB*/
			n=1;//number of files we need to add to them tags
			q=session.createQuery("select f from files f where f.ID=" +
			"(select max(f.ID) from files f )" );
			myfile=q.list();
			fileID=myfile.iterator().next().getID();
			fileID++;
			files myFile=new files();
			myFile.setID(fileID);
			myFile.setName(filename);
			myFile.setLast_m(last_m);
			//myFile.setTags(tags);
			myFile.setPath(path);
			Manager<files> manger=new Manager<files>(session);
			manger.save(myFile);
			 q=session.createQuery("select f from files f where f.ID=" +
				"(select max(f.ID) from files f )" );
			 myfile=q.list();
			 fileID=myfile.iterator().next().getID();
			 fileIDarr[0]=fileID;
		}
		else{
			n=0;
			Iterator<files>it=q.list().iterator();
			while(it.hasNext()){
				
				fileIDarr[n]=it.next().getID();
				n++;          
			}
		}
		//////////////////////////////////////		
		//System.out.println(tags.length);
		Manager<DataTagsToFiles> tagManger=new Manager<DataTagsToFiles>(session);
		DataTagsToFiles tagToFile;
		for(int j=0;j<n;j++){
			for(int i=0;i<tags.length;i++){
				tagToFile= new DataTagsToFiles();
				tagToFile.setFileID(fileIDarr[j]);
				tagToFile.setTag(tags[i]);
				tagManger.save(tagToFile);
			}
		}
		session.flush();
		session.close();
		/*
		 * checked- this method works
		 */
		
	}
	/**
	 * with this method I delete a file from the database ,
	 * and all its connected tags
	 * @param f -File
	 */
	public void deleteFile(File f){
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		String qSt=
			"select f "+
			"from  files f "+
			"where f.name=:rep1 and f.path=:rep2";
		Query q=session.createQuery(qSt).setParameter("rep1",f.getName()).setParameter("rep2",f.getPath());
		Iterator<files>myItf=q.list().iterator();
		while(myItf.hasNext()){
		/*
		 * first I delete all the tags that connceted to this file
		 */
			int fileID=myItf.next().getID();
			qSt=
				"select t "+
				"from  DataTagsToFiles t "+
				"where t.fileID= :rep1";
			q=session.createQuery(qSt).setParameter("rep1",fileID);
			List<DataTagsToFiles> mytags=q.list();
			Manager<DataTagsToFiles> tagsManger=new Manager<DataTagsToFiles>(session);
			Iterator <DataTagsToFiles>itTags=mytags.iterator();
			while (itTags.hasNext()){
				tagsManger.delete(itTags.next());
			}
		/*
		 * second - I delete the file itself
		 */
			Manager<files> manger=new Manager<files>(session);
			qSt=
				"select f "+
				"from  files f "+
				"where f.ID= :rep1";
			q=session.createQuery(qSt).setParameter("rep1",fileID);
		//Query q=session.createQuery(qStatment);
			List<files> myfiles=q.list();
			Iterator <files>it=myfiles.iterator();
			if(it.hasNext()){
				manger.delete(it.next());
			}
		}
		session.flush();
		session.close();
		/*
		 * checked- this method works
		 */
	}
	/**
	 * @param file f ,String tag
	 * this method delete only one tag of  file f
	 */
	public void deleteOneTag(File f, String tag) {
		/*
		 * first to detect this file fileID
		 * 
		 */
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		String qSt=
			"select f "+
			"from  files f "+
			"where f.name=:rep1 and f.path=:rep2";
		Query q=session.createQuery(qSt).setParameter("rep1",f.getName()).setParameter("rep2",f.getPath());
		Iterator<files>myItf=q.list().iterator();
		while(myItf.hasNext()){
			int fileID=myItf.next().getID();//the fileID
			/*
			 * second - to find this tag in order to delete it
			 */
			qSt=
				"select t "+
				"from  DataTagsToFiles t "+
				"where t.tag=:rep1 and t.fileID=:rep2";
			q=session.createQuery(qSt).setParameter("rep1",tag).setParameter("rep2",fileID);
			Manager<DataTagsToFiles> tManger=new Manager<DataTagsToFiles>(session);
			Iterator<DataTagsToFiles>it=q.list().iterator();
			while(it.hasNext()){
				tManger.delete(it.next());
			}
		}
		session.flush();
		session.close();
		
	}
	/**
	 * Removes all tags from the table inside DB
	 */
	public void FlushTags(){
		//SessionFactory sessionQFactory = new Configuration().configure().buildSessionFactory();
		if(sessionQFactory!=null)
		{
			System.out.println("sessionFactory  work");
		}
		Session session = sessionQFactory.openSession();
		if(session!=null){
			System.out.println("session work");
		}
		String Q="DELETE FROM DataTagsToFiles";
		Query query=session.createQuery(Q);
		query.executeUpdate();
		session.flush();
		session.close();
	}
	/**
	 * @author Shinichi
	 * adds a file to DB
	 */
	public void addFile(File f) {
		Session session=sessionQFactory.openSession();
		Manager<files> man = new Manager<files>(session);
		files toput=new files();
		toput.setName(f.getName());
		toput.setPath(f.getPath());
		Long mod=f.lastModified();
		Date date = new Date(mod);
		toput.setLast_m(date.toString());
		man.save(toput);
		session.flush();
		session.close();
	}
	

	
	
	
	
}
